package com.clp.protocol.iec104.iec104.server.slavechannel.pipeline;

import com.clp.protocol.iec104.iec104.server.slave.SlaveControlConfig;
import com.clp.protocol.iec104.iec104.server.slave.SlaveDataConfig;
import com.clp.protocol.iec104.iec104.server.slavechannel.InSlaveChannel;
import com.clp.protocol.iec104.iec104.server.slavechannel.pipeline.codec.ApduToBytesSlaveChannelEncoder;
import com.clp.protocol.iec104.iec104.server.slavechannel.pipeline.codec.BytesToApduSlaveChannelDecoder;
import com.clp.protocol.iec104.iec104.server.slavechannel.pipeline.codec.CompleteApduSlaveChannelDecoder;
import com.clp.protocol.iec104.iec104.server.slavechannel.pipeline.filter.RemoteIpFilterSlaveChannelHandler;
import com.clp.protocol.iec104.iec104.server.slavechannel.pipeline.state.GateStateHandler;
import com.clp.protocol.iec104.iec104.server.slavechannel.pipeline.state.control.*;
import com.clp.protocol.iec104.iec104.server.slavechannel.pipeline.state.data.TcDataStateHandler;
import com.clp.protocol.iec104.iec104.server.slavechannel.pipeline.state.data.TotalCall100DataStateHandler;
import com.clp.protocol.iec104.iec104.server.slavechannel.pipeline.state.data.TotalCall101DataStateHandler;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelPipeline;
import lombok.Getter;

/**
 * 流水线管理
 */
public class PipelineManager implements ControlInfo {
    @Getter
    private final InSlaveChannel inSlaveChannel;
    private final ChannelPipeline pipeline;

    private final RemoteIpFilterSlaveChannelHandler remoteIpFilterSlaveChannelHandler;

    private final CompleteApduSlaveChannelDecoder completeApduSlaveChannelDecoder;
    private final BytesToApduSlaveChannelDecoder bytesToApduSlaveChannelDecoder;
    private final ApduToBytesSlaveChannelEncoder apduToBytesSlaveChannelEncoder;

    private final ApduLogControlStateHandler apduLogControlStateHandler;
    private final T0T1T2T3ControlStateHandler t0T1T2T3ControlStateHandler; // T0T1T2T3控制 keepAlive
    private final DtControlStateHandler dtControlStateHandler; // 启动传输控制
    private final InitControlStateHandler initializeControlStateHandler; // 初始化结束

    private final GateStateHandler gateStateHandler;

    private final TotalCall100DataStateHandler totalCall100DataStateHandler;
    private final TotalCall101DataStateHandler totalCall101DataStateHandler;
    private final TcDataStateHandler tcDataStateHandler;

    @Getter
    private final InternalUApduSender uApduSender;
    @Getter
    private final InternalSApduSender sApduSender;
    @Getter
    private final InternalIAsduSender iAsduSender;

    public PipelineManager(InSlaveChannel inSlaveChannel, SlaveControlConfig controlConfig, SlaveDataConfig dataConfig) {
        this.inSlaveChannel = inSlaveChannel;
        this.pipeline = inSlaveChannel.channel().pipeline();

        /*********************** 添加默认的处理器 *************************************/
        // 解码前、编码后处理器链
        // IP白名单过滤器
        this.remoteIpFilterSlaveChannelHandler = addLast(new RemoteIpFilterSlaveChannelHandler(this, controlConfig.getIpFilterRule()));

        // 编解码处理器
        // 解码器，解决粘包半包问题
        this.completeApduSlaveChannelDecoder = addLast(new CompleteApduSlaveChannelDecoder(this));
        // 解码器，将协议内容转换成入站消息对象
        this.bytesToApduSlaveChannelDecoder = addLast(new BytesToApduSlaveChannelDecoder(this));
        // 编码器，将出站消息对象转换成协议内容
        this.apduToBytesSlaveChannelEncoder = addLast(new ApduToBytesSlaveChannelEncoder(this));

        // 解码后、编码前的控制处理器链
        this.apduLogControlStateHandler = addLast(new ApduLogControlStateHandler(this)); // apdu IO 日志
        this.t0T1T2T3ControlStateHandler = addLast(new T0T1T2T3ControlStateHandler(this, controlConfig)); // 链路keepAlive
        this.dtControlStateHandler = addLast(new DtControlStateHandler(this)); // 控制和设置启动传输标志
        this.initializeControlStateHandler = addLast(new InitControlStateHandler(this)); // 初始化结束

        // 中间处理器，用于将apdu拆装为asdu
        this.gateStateHandler = addLast(new GateStateHandler(this, controlConfig)); //

        // 解码后、编码前的数据处理器链
        this.totalCall100DataStateHandler = addLast(new TotalCall100DataStateHandler(this, dataConfig)); // 总召唤100 - 遥测、遥信
        this.totalCall101DataStateHandler = addLast(new TotalCall101DataStateHandler(this, dataConfig)); // 总召唤101 - 遥脉
        this.tcDataStateHandler = addLast(new TcDataStateHandler(this, dataConfig));

        // 发送器
        this.uApduSender = new InternalUApduSender(this);
        this.sApduSender = new InternalSApduSender(this);
        this.iAsduSender = new InternalIAsduSender(this, gateStateHandler);
    }

    private <H extends ChannelHandler> H addLast(H handler) {
        pipeline.addLast(handler);
        return handler;
    }

    @Override
    public boolean isInitCompleted() {
        return initializeControlStateHandler.isInitCompleted();
    }

    @Override
    public boolean isStartedDt() {
        return dtControlStateHandler.isStartedDt();
    }

    @Override
    public int k() {
        return gateStateHandler.getK();
    }

    @Override
    public int w() {
        return gateStateHandler.getW();
    }

    @Override
    public int t0() {
        return t0T1T2T3ControlStateHandler.getT0();
    }

    @Override
    public int t1() {
        return t0T1T2T3ControlStateHandler.getT1();
    }

    @Override
    public int t2() {
        return t0T1T2T3ControlStateHandler.getT2();
    }

    @Override
    public int t3() {
        return t0T1T2T3ControlStateHandler.getT3();
    }

    @Override
    public int sendSeq() {
        return gateStateHandler.getSendSeq();
    }

    @Override
    public int recvSeq() {
        return gateStateHandler.getRecvSeq();
    }
}
